package com.stark.commons.spring.web.support.feign;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 自定义 feign 错误解码器。
 * <p>根据响应错误码区分业务异常，不走熔断器。
 * @author Ben
 * @since 1.0.0
 * @version 1.0.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class FeignErrorDecoder implements ErrorDecoder {
	
	private Map<Integer, String> codes;

	@Override
	public Exception decode(String methodKey, Response response) {
		if (MapUtils.isNotEmpty(codes) && codes.containsKey(response.status())) {
			String errmsg = codes.get(response.status());
			if (StringUtils.isBlank(errmsg)) {
				try {
					String jsonStr = Util.toString(response.body().asReader(StandardCharsets.UTF_8));
					JsonNode exception = new ObjectMapper().readTree(jsonStr);
					errmsg = exception.get("message").asText();
				} catch (IOException e) {
					errmsg = "未知业务异常";
					log.error("feign.Response 转 Exception 失败", e);
				}
			}
			errmsg = response.request().httpMethod() + " " + response.request().url() + " " + methodKey + " : " + errmsg;
			return new HystrixBadRequestException(errmsg);
		}
        return FeignException.errorStatus(methodKey, response);
	}

}
